<template>
  <div class="editor-main-container">
    <div
      :class="`editor-zoomable-container editor-${
        pageOptions?.layout || 'page'
      }-container editor-scrollbar`"
    >
      <div
        class="editor-zoomable-content"
        :style="{
          width: pageZoomWidth,
          height: pageZoomHeight,
        }"
      >
        <!-- 水印容器 -->
        <Watermark class="editor-page-content" :style="pageContentStyle">
          <!-- 页面头部 -->
          <div class="editor-page-node-header" contenteditable="false">
            <div
              class="editor-page-corner corner-tl"
              style="width: var(--editor-page-margin-left)"
            ></div>
            <div class="editor-page-node-header-content"></div>
            <div
              class="editor-page-corner corner-tr"
              style="width: var(--editor-page-margin-right)"
            ></div>
          </div>

          <!-- 编辑器内容区域 -->
          <div class="editor-page-node-content">
            <EditorContent />
          </div>

          <!-- 页面底部 -->
          <div class="editor-page-node-footer" contenteditable="false">
            <div
              class="editor-page-corner corner-bl"
              style="width: var(--editor-page-margin-left)"
            ></div>
            <div class="editor-page-node-footer-content"></div>
            <div
              class="editor-page-corner corner-br"
              style="width: var(--editor-page-margin-right)"
            ></div>
          </div>
        </Watermark>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  inject,
  computed,
  ref,
  watch,
  onMounted,
  onBeforeUnmount,
  nextTick,
  type Ref,
} from "vue";
import EditorContent from "../editor/index.vue";
import Watermark from "./Watermark.vue";
import type { PageOption } from "../../types";

defineOptions({
  name: "PageContainer",
});

// 注入依赖
const container = inject<Ref<string>>("container");
const pageOptions = inject<Ref<PageOption>>("page");

// 页面大小
const pageSize = computed(() => {
  const { width, height } = pageOptions?.value?.size ?? { width: 0, height: 0 };
  return {
    width: pageOptions?.value?.orientation === "portrait" ? width : height,
    height: pageOptions?.value?.orientation === "portrait" ? height : width,
  };
});

// 页面内容样式
const pageContentStyle = computed(() => {
  const background = pageOptions?.value?.background || "#ffffff";
  const style: Record<string, string> = {
    "--editor-page-orientation": pageOptions?.value?.orientation || "portrait",
    "--editor-page-background": background,
    "--editor-page-margin-top": (pageOptions?.value?.margin?.top ?? "0") + "cm",
    "--editor-page-margin-bottom":
      (pageOptions?.value?.margin?.bottom ?? "0") + "cm",
    "--editor-page-margin-left":
      (pageOptions?.value?.margin?.left ?? "0") + "cm",
    "--editor-page-margin-right":
      (pageOptions?.value?.margin?.right ?? "0") + "cm",
    "--editor-page-width":
      pageOptions?.value?.layout === "page"
        ? pageSize.value.width + "cm"
        : "auto",
    "--editor-page-height":
      pageOptions?.value?.layout === "page"
        ? pageSize.value.height + "cm"
        : "100%",
    width:
      pageOptions?.value?.layout === "page"
        ? pageSize.value.width + "cm"
        : "100%",
    transform: `scale(${
      pageOptions?.value?.zoomLevel ? pageOptions.value.zoomLevel / 100 : 1
    })`,
    background: background,
  };

  // 如果是点阵底纹，添加 background-size 和 background-position
  if (background?.includes("radial-gradient")) {
    style.backgroundSize = "20px 20px";
    style.backgroundPosition = "0 0, 10px 10px";
  }

  return style;
});

// 页面缩放后的大小
const pageZoomWidth = computed(() => {
  if (pageOptions?.value?.layout === "web") {
    return "100%";
  }
  return `calc(${pageSize?.value?.width}cm * ${
    pageOptions?.value?.zoomLevel ? pageOptions?.value?.zoomLevel / 100 : 1
  })`;
});

// 页面内容变化后更新页面高度
let pageZoomHeight = ref("");
let heightUpdateTimer: ReturnType<typeof setTimeout> | null = null;
let rafId1: number | null = null;
let rafId2: number | null = null;
let isUpdatingHeight = false;
let isComponentMounted = true; // 标记组件是否已挂载

const setPageZoomHeight = () => {
  // 如果组件已卸载，不再执行
  if (!isComponentMounted) return;

  // 清除之前的定时器和动画帧
  if (heightUpdateTimer) {
    clearTimeout(heightUpdateTimer);
    heightUpdateTimer = null;
  }
  if (rafId1 !== null) {
    cancelAnimationFrame(rafId1);
    rafId1 = null;
  }
  if (rafId2 !== null) {
    cancelAnimationFrame(rafId2);
    rafId2 = null;
  }

  if (isUpdatingHeight) return;
  isUpdatingHeight = true;

  if (!pageOptions?.value) {
    isUpdatingHeight = false;
    return;
  }

  if (pageOptions.value.layout === "web") {
    pageZoomHeight.value = "auto";
    isUpdatingHeight = false;
    return;
  }

  // 使用多重延迟确保 DOM 完全渲染
  // 1. 先等待 Vue 的 nextTick
  nextTick(() => {
    if (!isComponentMounted) {
      isUpdatingHeight = false;
      return;
    }

    // 2. 再等待浏览器渲染帧
    rafId1 = requestAnimationFrame(() => {
      if (!isComponentMounted) {
        isUpdatingHeight = false;
        rafId1 = null;
        return;
      }

      // 3. 再次等待下一帧，确保布局完成
      rafId2 = requestAnimationFrame(() => {
        if (!isComponentMounted) {
          isUpdatingHeight = false;
          rafId1 = null;
          rafId2 = null;
          return;
        }

        // 4. 最后使用 setTimeout 给浏览器更多时间处理大量内容
        heightUpdateTimer = setTimeout(() => {
          if (!isComponentMounted) {
            isUpdatingHeight = false;
            heightUpdateTimer = null;
            return;
          }

          const el = document.querySelector(
            `${container?.value || ""} .editor-page-content`
          ) as HTMLElement;

          if (!el) {
            isUpdatingHeight = false;
            heightUpdateTimer = null;
            return;
          }

          // 获取实际高度，优先使用 scrollHeight（包含所有内容）
          // 如果内容被裁剪，使用 scrollHeight；否则使用 clientHeight
          const contentHeight =
            el.scrollHeight > el.clientHeight
              ? el.scrollHeight
              : el.clientHeight;

          const zoomLevel = pageOptions?.value?.zoomLevel ?? 100;
          const scaledHeight = (contentHeight * zoomLevel) / 100;
          pageZoomHeight.value = `${scaledHeight}px`;

          isUpdatingHeight = false;
          heightUpdateTimer = null;
        }, 150); // 给大量内容更多渲染时间
      });
    });
  });
};

// 监听页面配置变化
onMounted(() => {
  void setPageZoomHeight();
});

watch(
  () => [
    pageOptions?.value?.layout,
    pageOptions?.value?.zoomLevel,
    pageOptions?.value?.size,
    pageOptions?.value?.orientation,
  ],
  () => {
    void setPageZoomHeight();
  },
  { deep: true }
);

// 编辑器内容发生变化后，自动调整页面高度
const editorInstance = inject<Ref<any>>("editor");

// 使用 ResizeObserver 和 MutationObserver 监听变化
let resizeObserver: ResizeObserver | null = null;
let mutationObserver: MutationObserver | null = null;
const contentElementRef = ref<HTMLElement | null>(null);
const editorContentRef = ref<HTMLElement | null>(null);

// 监听编辑器实例变化，注册事件监听
let updateHandler: (() => void) | null = null;
let transactionHandler: (() => void) | null = null;

watch(
  () => editorInstance?.value,
  (editor, oldEditor) => {
    // 先移除旧编辑器的事件监听
    if (oldEditor && updateHandler && transactionHandler) {
      oldEditor.off("update", updateHandler);
      oldEditor.off("transaction", transactionHandler);
    }

    if (!editor) return;

    // 创建事件处理函数
    updateHandler = () => {
      setPageZoomHeight();
    };
    transactionHandler = () => {
      setPageZoomHeight();
    };

    // 监听编辑器的 update 事件（每次内容变化都会触发）
    editor.on("update", updateHandler);

    // 监听编辑器的 transaction 事件（更底层的内容变化）
    editor.on("transaction", transactionHandler);
  },
  { immediate: true }
);

// 使用 ResizeObserver 和 MutationObserver 监听内容区域变化
onMounted(() => {
  isComponentMounted = true;

  nextTick(() => {
    // 如果组件在 nextTick 之前已经卸载，不再执行
    if (!isComponentMounted) return;

    // 监听内容区域尺寸变化
    const contentEl = document.querySelector(
      `${container?.value || ""} .editor-page-node-content`
    ) as HTMLElement;

    if (contentEl && isComponentMounted) {
      contentElementRef.value = contentEl;
      resizeObserver = new ResizeObserver(() => {
        if (isComponentMounted) {
          setPageZoomHeight();
        }
      });
      resizeObserver.observe(contentEl);
    }

    // 监听编辑器 DOM 变化（MutationObserver 可以检测到 DOM 结构变化）
    const editorEl = document.querySelector(
      `${container?.value || ""} .editor-prosemirror`
    ) as HTMLElement;

    if (editorEl && isComponentMounted) {
      editorContentRef.value = editorEl;
      mutationObserver = new MutationObserver(() => {
        if (isComponentMounted) {
          setPageZoomHeight();
        }
      });
      mutationObserver.observe(editorEl, {
        childList: true, // 监听子节点变化
        subtree: true, // 监听所有后代节点
        characterData: true, // 监听文本内容变化
        attributes: false, // 不需要监听属性变化
      });
    }
  });
});

// 组件卸载时清理所有资源
onBeforeUnmount(() => {
  // 标记组件已卸载
  isComponentMounted = false;

  // 清理定时器
  if (heightUpdateTimer) {
    clearTimeout(heightUpdateTimer);
    heightUpdateTimer = null;
  }

  // 清理动画帧
  if (rafId1 !== null) {
    cancelAnimationFrame(rafId1);
    rafId1 = null;
  }
  if (rafId2 !== null) {
    cancelAnimationFrame(rafId2);
    rafId2 = null;
  }

  // 清理编辑器事件监听
  if (editorInstance?.value && updateHandler && transactionHandler) {
    editorInstance.value.off("update", updateHandler);
    editorInstance.value.off("transaction", transactionHandler);
    // 置空引用，帮助 GC
    updateHandler = null;
    transactionHandler = null;
  }

  // 清理 ResizeObserver
  if (resizeObserver) {
    if (contentElementRef.value) {
      resizeObserver.unobserve(contentElementRef.value);
    }
    resizeObserver.disconnect();
    resizeObserver = null;
  }

  // 清理 MutationObserver
  if (mutationObserver) {
    mutationObserver.disconnect();
    mutationObserver = null;
  }

  // 置空 DOM 引用
  contentElementRef.value = null;
  editorContentRef.value = null;
});
</script>

<style lang="scss" scoped>
.editor-main-container {
  height: 100%;
  display: flex;
  position: relative;
}

.editor-zoomable-container {
  flex: 1;
  scroll-behavior: smooth;
  overflow: auto;

  &.editor-page-container {
    padding: 20px 50px;
    box-sizing: border-box;

    .editor-zoomable-content {
      margin: 0 auto;
      box-shadow: rgba(0, 0, 0, 0.06) 0px 0px 10px 0px,
        rgba(0, 0, 0, 0.04) 0px 0px 0px 1px;
    }
  }

  &.editor-web-container {
    display: flex;

    .editor-zoomable-content {
      flex: 1;

      .editor-page-corner {
        display: none;
      }

      .editor-page-content {
        min-height: 100%;

        .editor-page-node-content {
          min-height: 100px;
        }
      }
    }
  }

  .editor-page-content {
    transform-origin: 0 0;
    box-sizing: border-box;
    display: flex;
    position: relative;
    background: var(--editor-page-background);
    width: var(--editor-page-width);
    min-height: var(--editor-page-height);
    overflow: visible !important;
    flex-direction: column;

    [contenteditable] {
      outline: none;
    }
  }
}

.editor-page-node-header {
  height: var(--editor-page-margin-top);
  overflow: hidden;
  display: flex;
  justify-content: space-between;
}

.editor-page-node-footer {
  height: var(--editor-page-margin-bottom);
  overflow: hidden;
  display: flex;
  justify-content: space-between;
}

.editor-page-corner {
  box-sizing: border-box;
  position: relative;
  z-index: 10;

  @media print {
    opacity: 0;
  }

  &::after {
    position: absolute;
    content: "";
    display: block;
    height: 1cm;
    width: 1cm;
    border: solid 1px rgba(0, 0, 0, 0.08);
  }

  &.corner-tl::after {
    border-top: none;
    border-left: none;
    bottom: 0;
    right: 0;
  }

  &.corner-tr::after {
    border-top: none;
    border-right: none;
    bottom: 0;
    left: 0;
  }

  &.corner-bl::after {
    border-bottom: none;
    border-left: none;
    top: 0;
    right: 0;
  }

  &.corner-br::after {
    border-bottom: none;
    border-right: none;
    top: 0;
    left: 0;
  }
}

.editor-page-node-header-content,
.editor-page-node-footer-content {
  flex: 1;
}

.editor-page-node-content {
  position: relative;
  box-sizing: border-box;
  flex-shrink: 1;
}

/* 自定义滚动条 */
.editor-scrollbar::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.editor-scrollbar::-webkit-scrollbar-track {
  background: var(--editor-container-background);
  border-radius: 4px;
}

.editor-scrollbar::-webkit-scrollbar-thumb {
  background: var(--editor-scrollbar-thumb-color);
  border-radius: 4px;
}

.editor-scrollbar::-webkit-scrollbar-thumb:hover {
  background: var(--editor-scrollbar-thumb-hover-color);
}
</style>
